package ar.com.spsolutions.splilabrary.view.pages;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;

import ar.com.spsolutions.splibrary.notifiers.INotifier;
import ar.com.spsolutions.splibrary.services.EntityService;
import ar.com.spsolutions.splibrary.services.LibraryServiceFacade;
import ar.com.spsolutions.splibrary.user.User;
import ar.com.spsolutions.splilabrary.view.application.WebSession;
import ar.com.spsolutions.splilabrary.view.pages.components.PopinNotifier;
import ar.com.spsolutions.splilabrary.view.pages.home.PageContainer;
import ar.com.spsolutions.splilabrary.view.version2.components.AbstractNavigatorBar;
import ar.com.spsolutions.splilabrary.view.version2.components.MainContainer;
import ar.com.spsolutions.splilabrary.view.version2.components.MenuPanel;

public abstract class BasePage extends WebPage {
	private static final long serialVersionUID = 1463165259043471374L;

	private static List<Class<? extends BasePage>> navigatorMenues = new ArrayList<Class<? extends BasePage>>();

	public static void addPage(final Class<? extends BasePage> page) {
		BasePage.navigatorMenues.add(page);
	}

	@SpringBean(name = "service.entity")
	private transient EntityService entityService;

	@SpringBean(name = "service.notifier")
	private transient INotifier notifier;

	@SpringBean
	private LibraryServiceFacade libraryServiceFacade;

	private MainContainer container;

	private PopinNotifier popinNotifier;

	public BasePage() {
		super();
		this.initialize();
	}

	private void initialize() {
		this.addSignIn();
		this.add(this.getNavigatorBar());
		this.add(this.getMenuBar());
		this.container = new PageContainer();
		this.add(this.container);
		this.popinNotifier = new PopinNotifier("notifier");
		this.add(this.popinNotifier);
		this.setOutputMarkupId(true);
		this.setGuestCredentials();
	}

	private void setGuestCredentials() {
		((WebSession) this.getSession()).setGuestCredentials();
	}

	private void addSignIn() {
		this.add(new SignIn("loginPanel"));
		final WebSession webSession = (WebSession) this.getSession();
		final User user = webSession.getUser();
		final String name = user == null ? "Guest" : user.getName();

		this.add(new Label("userNameSpan", name));

		final Label signInLabel = new Label("toggleButtonSignIn",
				new ResourceModel("toggleButtonSignIn"));
		signInLabel.setVisible(!webSession.isSignedIn());
		this.add(signInLabel);

		final Label closeLabel = new Label("toggleButtonClose",
				new ResourceModel("toggleButtonClose"));
		closeLabel.setVisible(!webSession.isSignedIn());
		this.add(closeLabel);

		final Label signOutLink = new Label("toggleButtonSignOut",
				new ResourceModel("toggleButtonSignOut"));
		signOutLink.add(new AjaxEventBehavior("onclick") {

			private static final long serialVersionUID = -8607897209332239307L;

			@Override
			protected void onEvent(final AjaxRequestTarget target) {
				webSession.invalidate();
				webSession.setUser(null);
				BasePage.this.getPage().setResponsePage(Home.class);
			}
		});
		webSession.setUser(user);
		signOutLink.setVisible(webSession.isSignedIn());
		this.add(signOutLink);
	}

	private Component getMenuBar() {
		return new MenuPanel(this.getMenues());
	}

	public abstract Map<String, Class<? extends MainContainer>> getMenues();

	private AbstractNavigatorBar getNavigatorBar() {
		return new AbstractNavigatorBar(BasePage.navigatorMenues);
	}

	// --accessors--
	public EntityService getEntityService() {
		return this.entityService;
	}

	public void setEntityService(final EntityService entityService) {
		this.entityService = entityService;
	}

	public INotifier getNotifier() {
		return this.notifier;
	}

	public void setNotifier(final INotifier notifier) {
		this.notifier = notifier;
	}

	private MainContainer getContainer() {
		return this.container;
	}

	public void setContainer(final MainContainer container) {
		this.remove(this.getContainer());
		this.container = container;
		this.add(container);
	}

	public LibraryServiceFacade getLibraryServiceFacade() {
		return this.libraryServiceFacade;
	}

	public void setLibraryServiceFacade(
			final LibraryServiceFacade libraryServiceFacade) {
		this.libraryServiceFacade = libraryServiceFacade;
	}

	public PopinNotifier getPopinNotifier() {
		return this.popinNotifier;
	}

	public void setPopinNotifier(final PopinNotifier popinNotifier) {
		this.popinNotifier = popinNotifier;
	}

}
